home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 June / EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso / earcd / dtype / fontdt12.lha / Src / dispatch.c < prev    next >
C/C++ Source or Header  |  1996-05-06  |  17KB  |  545 lines

  1. /*
  2. **    dispatch.c - dispatcher for Font DataType class
  3. **    Copyright © 1995-96 Michael Letowski
  4. */
  5.  
  6. #include <exec/types.h>
  7. #include <exec/memory.h>
  8. #include <dos/dos.h>
  9. #include <graphics/displayinfo.h>
  10. #include <graphics/gfx.h>
  11. #include <graphics/modeid.h>
  12. #include <graphics/rastport.h>
  13. #include <graphics/text.h>
  14. #include <intuition/classes.h>
  15. #include <datatypes/datatypes.h>
  16. #include <datatypes/datatypesclass.h>
  17. #include <datatypes/pictureclass.h>
  18. #include <diskfont/diskfont.h>
  19. #include <utility/hooks.h>
  20. #include <utility/tagitem.h>
  21. #include <support/types.h>
  22. #include <support/graphics.h>
  23.  
  24. #include <stdlib.h>
  25.  
  26. #include <proto/dos.h>
  27. #include <proto/exec.h>
  28. #include <proto/diskfont.h>
  29. #include <proto/datatypes.h>
  30. #include <proto/graphics.h>
  31. #include <proto/intuition.h>
  32. #include <proto/utility.h>
  33. #include <clib/support_protos.h>
  34.  
  35. #include "classbase.h"
  36. #include "dispatch.h"
  37. #include "prefs.h"
  38. #include "otag.h"
  39.  
  40.  
  41. /****** font.datatype/font.datatype *****************************************
  42. *
  43. *   NAME
  44. *       font.datatype -- data type for Amiga bitmap and outline fonts.
  45. *
  46. *   FUNCTION
  47. *       The font data type, a sub-class of the picture.datatype, is used
  48. *       to load (and display) Amiga bitmap and outline fonts. All available
  49. *       sizes of a given font are loaded into memory and then rendered into
  50. *       screen, taking user preferences into account.
  51. *       By default this data type will render each font size in one line,
  52. *       in ascending order. Whole characters set for the given font and size
  53. *       will be rendered.
  54. *
  55. *       User preferences are stored in font.prefs file, located in either
  56. *       PROGDIR:Prefs/DataTypes/ or ENV:DataTypes/ directory (searched in
  57. *       that order). A preferences file is an ASCII file parsed with the
  58. *       following ReadArgs() template:
  59. *
  60. *           STRINGS/M,CENTER=CENTRE/S,INV=INVERSE/S,FN=FONTNAME/S,
  61. *           DPI/K,FG=FOREGROUND/K,BG=BACKGROUND/K
  62. *
  63. *       STRINGS are multiple texts that are to be rendered instead of the
  64. *       default character set. Each string is rendered in one line.
  65. *       CENTRE indicates that each line should be centered on screen.
  66. *       INVERSE indicates foreground/background color inversion. Does not
  67. *       work for color fonts.
  68. *       FONTNAME indicates that for each font's size the name and size of
  69. *       that font should be rendered before any user text.
  70. *       DPI describes font's aspect ratio, in XDPI/A/N,YDPI/A/N format.
  71. *       Default values for aspect ratio are DiskFont's defaults.
  72. *       FOREGROUND describes foreground color for two-color fonts. The string
  73. *       is parsed with R=RED/A/N,G=GREEN/A/N,B=BLUE/A/N template to extract
  74. *       red, green and blue components for a given color. Default foreground
  75. *       color is black. This option does not work for color fonts.
  76. *       BACKGROUND describes background color for two-color fonts. The string
  77. *       is parsed with R=RED/A/N,G=GREEN/A/N,B=BLUE/A/N template to extract
  78. *       red, green and blue components for a given color. Default background
  79. *       color is white. This option does not work for color fonts.
  80. *
  81. *   METHODS
  82. *       OM_NEW -- Create a new picture object from a .font file and all
  83. *                 associated size files. The source must be a file.
  84. *
  85. *   NOTES
  86. *       Since version 39.4 a font to be loaded does not need to be in
  87. *       FONTS: path. The data type will temporarily extend FONTS: assign
  88. *       to cover given font.
  89. *       If bitmaps are created for an outline font, the data type will load
  90. *       only those sizes, for which bitmaps exist. Otherwise all DiskFont
  91. *       default sizes will be loaded.
  92. *       For color fonts the color is set to that of biggest size.
  93. *
  94. *   BUGS
  95. *       Loading outline fonts with multiple size requires 'a lot' of memory.
  96. *       OpenDiskFont() uses a lot of stack and this causes problems with
  97. *       small-stack clients like original IPrefs.
  98. *
  99. *   SEE ALSO
  100. *       picture.datatype, diskfont.library, bullet.library.
  101. *
  102. *****************************************************************************
  103. *
  104. */
  105.  
  106.  
  107. /*
  108. **    Private constants
  109. */
  110. #define IDS_CNT                4                                                    /* Number of ModeIDs */
  111.  
  112. #define COL_WHITE            0xFF                                            /* 'white' colour */
  113. #define COL_BLACK            0x00                                            /* 'black' colour */
  114.  
  115. #define DEF_XDPI            72                                                /* Default X-axis DPI */
  116. #define DEF_YDPI            80                                                /* Default Y-axis DPI */
  117.  
  118. #define FONTSPATH            "FONTS"                                        /* Assign name without ':' */
  119.  
  120. /* 256 for ASCII set, 2 for terminator */
  121. #define MAX_CHAR            (256+2)
  122. /* 32 chars for font name, 6 for size, 2 for terminator */
  123. #define MAX_CHAR2            (32+6+2)
  124. /* Total number of strings */
  125. #define MAX_STRING        32
  126.  
  127. /* Get font's name */
  128. #define FontName(f)        ((f)->tf_Message.mn_Node.ln_Name)
  129.  
  130. /* Convenient cast */
  131. #define CFont(f)            ((struct ColorTextFont *)(f))
  132.  
  133. typedef int (SFUNC)(void const*, void const *);
  134.  
  135.  
  136. /*
  137. **    Private functions prototypes
  138. */
  139. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg);
  140. STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs);
  141.  
  142. /* Font management */
  143. STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
  144.                                                                         struct FontContentsHeader *fch, STRPTR name);
  145. STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt);
  146.  
  147. /* Rendering */
  148. STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  149.                                         struct TextFont *f, ULONG *w, ULONG *h);
  150. STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  151.                                         struct TextFont **f, ULONG cnt, ULONG w);
  152. STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt, 
  153.                                                         struct TextFont *f, ULONG *cnt);
  154. STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2);
  155.  
  156. /* DataTypes stubs */
  157. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  158. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...);
  159.  
  160.  
  161. /*
  162. **    Public functions
  163. */
  164. Class *InitClass(struct ClassBase *cb)
  165. {
  166.     Class *CL;
  167.  
  168.     /* Create our class (no instance) */
  169.     if(CL=MakeClass(DATATYPENAME,SUPERCLASSNAME,NULL,NULL,0))
  170.     {
  171.         CL->cl_Dispatcher.h_Entry=(HOOKFUNC)Dispatch;
  172.         CL->cl_UserData=(ULONG)cb;
  173.         AddClass(CL);
  174.     }
  175.     return(CL);
  176. }    /* InitClass */
  177.  
  178.  
  179. /*
  180. **    Level 1 private functions
  181. */
  182. STATIC ASM Object *Dispatch(R_A0 Class *cl, R_A2 Object *o, R_A1 Msg msg)
  183. {
  184.     struct ClassBase *cb=(struct ClassBase *)cl->cl_UserData;
  185.     Object *Obj;
  186.  
  187.     switch(msg->MethodID)
  188.     {
  189.         case OM_NEW:                                                                /* We know this method */
  190.             if(Obj=(Object *)DoSuperMethodA(cl,o,msg))
  191.                 unless(GetFont(cb,Obj,((struct opSet *)msg)->ops_AttrList))
  192.                 {
  193.                     CoerceMethod(cl,Obj,OM_DISPOSE);
  194.                     Obj=NULL;
  195.                 }
  196.             break;
  197.         default:                                                                        /* Let the superclass handle it */
  198.             Obj=(Object *)DoSuperMethodA(cl,o,msg);
  199.             break;
  200.     }
  201.     return(Obj);
  202. }    /* Dispatch */
  203.  
  204.  
  205. /*
  206. **    Level 2 private functions
  207. */
  208. STATIC LBOOL GetFont(struct ClassBase *cb, Object *o, struct TagItem *attrs)
  209. {
  210.     STATIC CONST ULONG SourceIDs[IDS_CNT]=                    /* Font flag->mode selector */
  211.     {
  212.         LORES_KEY,HIRES_KEY,LORESLACE_KEY,HIRESLACE_KEY
  213.     };    /* ModeIDs */
  214.  
  215.     struct RastPort RP;
  216.     struct Opts Opts;
  217.  
  218.     struct PrefsHandle *PH;
  219.     struct FileInfoBlock *FIB;
  220.     struct FontContentsHeader *FCH;
  221.     struct TextFont **Fonts=NULL,*F;
  222.     struct BitMapHeader *BMHD=NULL;
  223.     struct ColorFontColors *CFC;
  224.     struct ColorRegister *CMap=NULL;
  225.     LONG *CRegs=NULL;
  226.  
  227.     STRPTR Title,Name=NULL;                                                /* Font file name & picture title */
  228.     BPTR DirLock,FH=0;
  229.     ULONG TallWide,ModeID;
  230.     ULONG Width,Height,Depth;
  231.     ULONG I,J,NumFonts;
  232.     UBYTE ForeCol[3],BackCol[3],TCol;
  233.     LBOOL AFlag=FALSE,Result=FALSE;
  234.  
  235.     /* Read preferences */
  236.     PH=GetFontPrefs(cb,&Opts);
  237.  
  238.     /* Get default title */
  239.     Title=(STRPTR)GetTagData(DTA_Name,NULL,attrs);
  240.  
  241.     /* Get file handle and BitMapHeader */
  242.     LocGetDTAttrs(cb,o,DTA_Handle,&FH,PDTA_BitMapHeader,&BMHD,TAG_DONE);
  243.     try(FH && BMHD,    EXIT);
  244.  
  245.     /* Get font file name */
  246.     try(FIB=AllocDosObject(DOS_FIB,NULL),    NO_FIB);/* Create FileInfoBlock */
  247.     if(ExamineFH(FH,FIB))                                                    /* Examine it */
  248.         Name=FIB->fib_FileName;                                            /* Get name pointer */
  249.     unless(Name)                                                                    /* Still no name */
  250.         if(Title)                                                                        /* Use title to get name */
  251.             Name=FilePart(Title);                                            /* Get file part of title */
  252.     try(Name,    NO_NAME);
  253.  
  254.     /* Examine .font file, load sizes */
  255.     if(DirLock=ParentOfFH(FH))
  256.     {
  257.         if(FCH=NewFC(cb,DirLock,Name))
  258.         {
  259.             AFlag=AssignAdd(FONTSPATH,DirLock);
  260.             Fonts=OpenFonts(cb,&Opts,FCH,Name);
  261.             NumFonts=FCH->fch_NumEntries;
  262.             DisposeFC(cb,FCH);
  263.         }
  264.         if(AFlag)
  265.             RemAssignList(FONTSPATH,DirLock);
  266.         else
  267.             UnLock(DirLock);
  268.     }
  269.     try(Fonts,    NO_FONTS);                                                /* Check if any fonts loaded */
  270.  
  271.     /* Set colors */
  272.     for(I=0; I<3; I++)                                                        /* For each of RGB triad */
  273.     {
  274.         if(Opts.opt_ForeFlag)    ForeCol[I]=clamp(Opts.opt_ForeCol[I],0,255);
  275.         else                                    ForeCol[I]=COL_BLACK;
  276.         if(Opts.opt_BackFlag)    BackCol[I]=clamp(Opts.opt_BackCol[I],0,255);
  277.         else                                    BackCol[I]=COL_WHITE;
  278.     }
  279.  
  280.     /* Calculate sizes */
  281.     TallWide=0;
  282.     Width=Height=0;
  283.     Depth=1;
  284.     InitRastPort(&RP);                                                        /* Set up RastPort - here! */
  285.     for(I=0; I<NumFonts; I++)
  286.         if(F=Fonts[I])                                                            /* Opened successfully */
  287.         {
  288.             try(GetWH(cb,&RP,&Opts,F,&Width,&Height),    ERROR);
  289.             if(ftst(F->tf_Style,FSF_COLORFONT))                /* This is ColorFont */
  290.                 if(CFont(F)->ctf_Depth>Depth)                        /* Deeper? */
  291.                     Depth=CFont(F)->ctf_Depth;                        /* Set new depth */
  292.             TallWide=(F->tf_Flags & (FPF_TALLDOT | FPF_WIDEDOT))>>FPB_TALLDOT;
  293.         }
  294.  
  295.     /* Set up BitMap header */
  296.     BMHD->bmh_Width=Width;                                                /* Fill in informations */
  297.     BMHD->bmh_Height=Height;
  298.     BMHD->bmh_Depth=Depth;
  299.  
  300.     /* Get display mode id */
  301.     ModeID=BestModeID(BIDTAG_DesiredWidth,    Width,
  302.                                         BIDTAG_DesiredHeight,    Height,
  303.                                         BIDTAG_Depth,                    Depth,
  304.                                         BIDTAG_SourceID,            SourceIDs[TallWide & (IDS_CNT-1)],
  305.                                         TAG_DONE);
  306.  
  307.     /* Set colors */
  308.     LocSetDTAttrs(cb,o,PDTA_NumColors,1<<Depth,TAG_DONE);
  309.     LocGetDTAttrs(cb,o,PDTA_ColorRegisters,&CMap,PDTA_CRegs,&CRegs,TAG_DONE);
  310.     try(CMap && CRegs,    ERROR);
  311.     if(Depth==1)                                                                    /* B&W font */
  312.     {
  313.         if(Opts.opt_Inverse)                                                /* Inversion? */
  314.             for(I=0; I<3; I++)                                                /* For each of RGB triad */
  315.                 tswap(ForeCol[I],BackCol[I],TCol);            /* Swap foreground/background */
  316.         for(I=0; I<3; I++)                                                    /* For each of RGB triad */
  317.         {
  318.             ((UBYTE *)&CMap[0])[I]=BackCol[I];
  319.             CRegs[I+0]=Color32(BackCol[I]);
  320.             ((UBYTE *)&CMap[1])[I]=ForeCol[I];
  321.             CRegs[I+3]=Color32(ForeCol[I]);
  322.         }
  323.     }
  324.     else                                                                                    /* Some color fonts */
  325.         for(I=0; I<NumFonts; I++)                                        /* For each font */
  326.             if(F=Fonts[I])                                                        /* Is it valid? */
  327.                 if(ftst(F->tf_Style,FSF_COLORFONT))            /* Is it color? */
  328.                     if(CFC=CFont(F)->ctf_ColorFontColors)    /* Color table valid? */
  329.                         for(J=0; J<CFC->cfc_Count; J++)            /* Fore each color in table */
  330.                         {
  331.                             CMap[J].red=        (CFC->cfc_ColorTable[J] & 0x0F00)>>4;
  332.                             CRegs[J*3+0]=        Color32(CMap[J].red);
  333.                             CMap[J].green=    (CFC->cfc_ColorTable[J] & 0x00F0);
  334.                             CRegs[J*3+1]=        Color32(CMap[J].green);
  335.                             CMap[J].blue=        (CFC->cfc_ColorTable[J] & 0x000F)<<4;
  336.                             CRegs[J*3+2]=        Color32(CMap[J].blue);
  337.                         }
  338.  
  339.     /* Prepare bitmap */
  340.     if(RP.BitMap=AllocBitMap(Width,Height,Depth,BMF_CLEAR | BMF_INTERLEAVED,NULL))
  341.     {
  342.         /* Do rendering */
  343.         if(Result=Render(cb,&RP,&Opts,Fonts,NumFonts,Width))
  344.             LocSetDTAttrs(cb,o,DTA_ObjName,                Title,
  345.                                                     DTA_NominalHoriz,    Width,
  346.                                                     DTA_NominalVert,    Height,
  347.                                                     PDTA_BitMap,            RP.BitMap,
  348.                                                     PDTA_ModeID,            ModeID,
  349.                                                     TAG_DONE);
  350.         else                                                                                /* Could not render */
  351.             FreeBitMap(RP.BitMap);
  352.     }
  353.  
  354.     /* Cleanup */
  355.     catch(ERROR,        );
  356.     catch(NO_FONTS,    CloseFonts(cb,Fonts,NumFonts));
  357.     catch(NO_NAME,    );
  358.     catch(NO_FIB,        FreeDosObject(DOS_FIB,FIB));    /* MUST be freed here, not before! */
  359.     catch(EXIT,            );
  360.     if(PH)                    FreeFontPrefs(cb,PH);
  361.     return(Result);
  362. }    /* GetFont */
  363.  
  364.  
  365. /*
  366. **    Font management
  367. */
  368. STATIC struct TextFont **OpenFonts(struct ClassBase *cb, struct Opts *opts,
  369.                                                                         struct FontContentsHeader *fch, STRPTR name)
  370. {
  371.     struct TagItem MyTags[]=
  372.     {
  373.         {TA_DeviceDPI,    0},
  374.         {TAG_DONE,            0}
  375.     };    /* MyTags */
  376.  
  377.     struct TTextAttr TTA;
  378.  
  379.     struct TextFont **Fonts;
  380.     struct TFontContents *TFC;
  381.     LONG XDPI,YDPI;
  382.     ULONG I,NumEntries=fch->fch_NumEntries;
  383.     ULONG FCnt=0;                                                                    /* Number of opened fonts */
  384.  
  385.     try(Fonts=AllocVec(NumEntries*sizeof(APTR),MEMF_CLEAR),    NO_FONTS);
  386.     for(I=0; I<NumEntries; I++)
  387.     {
  388.         TFC=&TFontContents(fch)[I];                                /* Get FontContents */
  389.         TTA.tta_Name=name;                                                /* Copy attrs */
  390.         TTA.tta_YSize=TFC->tfc_YSize;
  391.         TTA.tta_Style=TFC->tfc_Style;
  392.         TTA.tta_Flags=TFC->tfc_Flags | FPF_DISKFONT;
  393.         if(ftst(TFC->tfc_Style,FSF_TAGGED))                /* Tags should be set */
  394.             TTA.tta_Tags=(struct TagItem *)
  395.                                         &TFC->tfc_FileName
  396.                                             [MAXFONTPATH-(TFC->tfc_TagCount*sizeof(struct TagItem))];
  397.         elif(opts->opt_DPIFlag)                                                /* DPI given - set our own DPI tags */
  398.         {
  399.             XDPI=clamp(opts->opt_XDPI,1,65535);
  400.             YDPI=clamp(opts->opt_YDPI,1,65535);
  401.             MyTags[0].ti_Data=(XDPI<<16) | YDPI;
  402.             TTA.tta_Tags=MyTags;
  403.             fset(TTA.tta_Style,FSF_TAGGED);
  404.         }
  405.         if(Fonts[I]=OpenDiskFont((struct TextAttr *)&TTA))
  406.             FCnt++;
  407.     }
  408.     unless(FCnt)                                                                    /* No font loaded */
  409.         throw2(SetIoErr(ERROR_OBJECT_NOT_FOUND),    ERROR);
  410.     qsort(Fonts,NumEntries,sizeof(APTR),(SFUNC *)SortFunc);
  411.     return(Fonts);
  412.  
  413.     catch(ERROR,        );
  414.     catch(NO_FONTS,    FreeVec(Fonts));
  415.     return(NULL);
  416. }    /* OpenFonts */
  417.  
  418. STATIC VOID CloseFonts(struct ClassBase *cb, struct TextFont **f, ULONG cnt)
  419. {
  420.     ULONG I;
  421.  
  422.     for(I=0; I<cnt; I++)
  423.         if(f[I])
  424.             CloseFont(f[I]);
  425.     FreeVec(f);
  426. }    /* CloseFonts */
  427.  
  428.  
  429. /*
  430. **    Rendering
  431. */
  432. STATIC LBOOL GetWH(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  433.                                         struct TextFont *f, ULONG *w, ULONG *h)
  434. {
  435.     STRPTR CurStr,*Strs;
  436.     ULONG W,J,SCnt;
  437.  
  438.     if(Strs=PrepStrings(cb,opt,f,&SCnt))                    /* Allocate and init strings */
  439.     {
  440.         /* Calculate sizes */
  441.         SetFont(rp,f);
  442.         for(J=0; J<SCnt; J++)
  443.         {
  444.             CurStr=Strs[J];
  445.             W=TextLength(rp,CurStr,strlen(CurStr));        /* Calculate len of this line */
  446.             if(W>*w)                                                                    /* If larger... */
  447.                 *w=W;                                                                        /* Make it new width */
  448.             *h+=f->tf_YSize;                                                    /* Add to height */
  449.         }
  450.         FreeVec(Strs);                                                            /* Free strings */
  451.     }
  452.     return(Strs!=NULL);
  453. }    /* GetWH */
  454.  
  455. STATIC LBOOL Render(struct ClassBase *cb, struct RastPort *rp, struct Opts *opt,
  456.                                         struct TextFont **f, ULONG cnt, ULONG w)
  457. {
  458.     struct TextFont *F;
  459.     STRPTR CurStr,*Strs;
  460.     ULONG SCnt,I,J,X,Y=0;
  461.     LBOOL Rendered=FALSE;
  462.  
  463.     for(I=0; I<cnt; I++)                                                    /* For each font size */
  464.         if(F=f[I])                                                                    /* Size opened? */
  465.             if(Strs=PrepStrings(cb,opt,F,&SCnt))            /* Allocate and init strings */
  466.             {
  467.                 Rendered=TRUE;
  468.                 /* Do rendering */
  469.                 SetFont(rp,F);                                                    /* Make it a current font */
  470.                 for(J=0; J<SCnt; J++)
  471.                 {
  472.                     CurStr=Strs[J];
  473.                     X=opt->opt_Center ? (w-TextLength(rp,CurStr,strlen(CurStr)))/2 : 0;
  474.                     Move(rp,X,Y+F->tf_Baseline);
  475.                     Text(rp,CurStr,strlen(CurStr));
  476.                     Y+=F->tf_YSize;
  477.                 }
  478.                 FreeVec(Strs);                                                    /* Free strings */
  479.             }
  480.     return(Rendered);
  481. }    /* Render */
  482.  
  483. STATIC STRPTR *PrepStrings(struct ClassBase *cb, struct Opts *opt, 
  484.                                                         struct TextFont *f, ULONG *cnt)
  485. {
  486.     STRPTR S1,S2,CurStr;
  487.     STRPTR *Strs,*Ss;
  488.     ULONG I,Cnt,Temp;
  489.  
  490.     /* Calculate number of strings */
  491.     Cnt=2;
  492.     if(Ss=opt->opt_Strings)                                                /* Strings given */
  493.         while(CurStr=*Ss++)                                                    /* For each string */
  494.             if(*CurStr)                                                                /* Non-empty string */
  495.                 Cnt++;                                                                    /* Increase count */
  496.  
  497.     /* Allocate and fill strings array */
  498.     if(Strs=AllocVec(Cnt*sizeof(STRPTR)+MAX_CHAR+MAX_CHAR2,MEMF_CLEAR))
  499.     {
  500.         S1=(STRPTR)Strs+Cnt*sizeof(STRPTR);
  501.         S2=S1+MAX_CHAR;
  502.         Cnt=0;
  503.         if(opt->opt_FontName && FontName(f))                /* FontName - first */
  504.         {
  505.             SNPrintf(S2,MAX_CHAR-1,"%s %ld",FontName(f),f->tf_YSize);
  506.             Strs[Cnt++]=S2;                                                        /* Init strings array */
  507.         }
  508.         Temp=Cnt;
  509.         if(Ss=opt->opt_Strings)                                            /* User's strings given */
  510.             while(CurStr=*Ss++)                                                /* While array not filled */
  511.                 if(*CurStr)                                                            /* Non-empty string */
  512.                     Strs[Cnt++]=CurStr;                                        /* Fill in array */
  513.         if(Cnt==0 || !Ss && Cnt==Temp)                            /* Use charset */
  514.         {
  515.             for(I=f->tf_LoChar; I<=f->tf_HiChar; I++)
  516.                 S1[I - f->tf_LoChar]=I ? (CHAR)I : ' ';    /* Make ASCII array */
  517.             Strs[Cnt++]=S1;
  518.         }
  519.         *cnt=Cnt;
  520.     }
  521.     return(Strs);
  522. }    /* PrepStrings */
  523.  
  524. STATIC LONG SortFunc(struct TextFont **tf1, struct TextFont **tf2)
  525. {
  526.     if(*tf1 && *tf2)    return((LONG)(*tf1)->tf_YSize - (*tf2)->tf_YSize);
  527.     else if(*tf1)            return(-1);
  528.     else if(*tf2)            return(1);
  529.     else                            return(0);
  530. }    /* SortFunc */
  531.  
  532.  
  533. /*
  534. **    DataTypes stubs
  535. */
  536. STATIC ULONG LocSetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  537. {
  538.     return(SetDTAttrsA(o,NULL,NULL,(struct TagItem *)&data));
  539. }    /* LocSetDTAttrs */
  540.  
  541. STATIC ULONG LocGetDTAttrs(struct ClassBase *cb, Object *o, ULONG data, ...)
  542. {
  543.     return(GetDTAttrsA(o,(struct TagItem *)&data));
  544. }    /* LocGetDTAttrs */
  545.